package blue.http.internal.core.parser;

import blue.base.core.path.FilePath;
import blue.base.core.reflect.BeanMethod;
import blue.base.core.reflect.JavaBean;
import blue.http.core.annotation.WebSocket;
import blue.http.core.exception.WebSocketServerException;
import blue.http.internal.core.parser.parameter.ParamParserFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * @author Jin Zheng
 * @since 1.0 2021-08-20
 */
public class WebSocketParser extends AbstractParser {
	private static Logger logger = LoggerFactory.getLogger(WebSocketParser.class);

	private final ParamParserFactory paramParserFactory;
	private final WebSocketConfigCache configCache;

	public WebSocketParser(ParamParserFactory paramParserFactory, WebSocketConfigCache configCache) {
		this.paramParserFactory = paramParserFactory;
		this.configCache = configCache;
	}

	@Override
	protected void parseMethod(JavaBean bean, BeanMethod method, FilePath rootPath) {
		var annotationWebSocket = bean.getAnnotation(WebSocket.class);
		String name = annotationWebSocket.name();
		FilePath uriPath = rootPath.copy();
		WebSocket annotationMethod = method.getAnnotation(WebSocket.class);
		if (annotationMethod != null) {
			uriPath.concat(annotationMethod.url());
			name = annotationMethod.name();
		}
		List<RequestParamConfig> paramConfigList = paramParserFactory.parse(method);
		String url = uriPath.getCurrentPath();
		DefaultWebSocketUrlConfig config = new DefaultWebSocketUrlConfig();
		config.setName(name.isEmpty() ? url : name);
		config.setUrl(url);
		config.setMethod(method);
		config.setParamList(paramConfigList);
		WebSocketUrlKey key = config.buildKey();

		if (configCache.contains(key)) {
			throw new WebSocketServerException("url 已经存在：" + key);
		}

		configCache.put(key, config);
		logger.info("Found WebSocket: {}，{}.{}()", config.getUrl(),
				bean.getTargetClass().getSimpleName(), method.getName());
	}

	@Override
	protected FilePath getRootPath(JavaBean bean) {
		WebSocket annotation = bean.getAnnotation(WebSocket.class);
		return FilePath.create(annotation.url());
	}

}
